package com.fc.im.netty;

import com.fc.im.netty.event.ChannelEvent;
import com.fc.im.netty.event.ChannelEventCause;
import com.fc.im.netty.event.ChannelEventListener;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerAdapter;
import io.netty.channel.ChannelHandlerContext;
import io.netty.util.AttributeKey;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * Created by ChanJiabo on 2017/1/14.
 */
public class ChannelManagerHandler extends ChannelHandlerAdapter {

    private static final Logger LOGGER = LoggerFactory.getLogger(ChannelManagerHandler.class);

    private static Map<String, Channel> anonymous =
            new ConcurrentHashMap<String, Channel>();

    private static Map<ChannelEvent.Type, ChannelEventListener> listeners =
            new ConcurrentHashMap<ChannelEvent.Type, ChannelEventListener>();

    //用户数据容器，线程安全
    private static AttributeKey<ConcurrentHashMap<String, Object>> ATT_USER_DATA =
            AttributeKey.valueOf("user_data");

    //唯一码
    private static AttributeKey<Object> ATT_IDENTITY
            = AttributeKey.valueOf("identity");

    private AttributeKey<Boolean> ATT_PROCEED =
            AttributeKey.valueOf("proceed");

    //http链接容器
    private static Map<Object, Channel> httpIdentities =
            new ConcurrentHashMap<Object, Channel>();

    //TCP 链接容器
    private static Map<Object, Channel> mobChannels =
            new ConcurrentHashMap<Object, Channel>();


    //PC版TCP链接容器
    private static Map<Object, Channel> pcChannels =
            new ConcurrentHashMap<Object, Channel>();

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        Channel session = ctx.channel();
        anonymous.put(session.id().asLongText(), session);
        LOGGER.info("Active:[{}]", session.id().asLongText());
        super.channelActive(ctx);
    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        Channel channel = ctx.channel();
        try{
            Object id = channel.attr(ATT_IDENTITY).get();
            fireClosedEvent(id, ChannelEventCause.NORMAL, channel);
        }catch (Exception e){
            LOGGER.error(e.getMessage());
        }
        anonymous.remove(channel.id().asLongText());
        LOGGER.info("Inactive:[{}]", channel.id().asLongText());
        super.channelInactive(ctx);
    }

    private void fireClosedEvent(Object identity, int cause, Channel session){
        ChannelEventListener listener = listeners.get(ChannelEvent.Type.CLOSED);
        if( listener == null) {
            return;
        }
        listener.onEvent(new ChannelEvent(cause, ChannelEvent.Type.CLOSED, identity, session));
    }
}
